let Fly;

// H5版本
// #ifdef H5
Fly = require('flyio/dist/npm/fly');
// #endif

//微信小程序和APP版本
// #ifndef H5
Fly = require('flyio/dist/npm/wx');
// #endif

import { baseURL as BASE_URL } from '@/config';
import { GET_MINI_PROGRAM_TOKEN_API } from '@/api/enums/basic';
import nuni, { loginAsync } from '@/utils/uni-api';

/**
 * 获取数据类型
 * @param arg
 * @returns {string}
 */
const getType = arg => {
  if (typeof arg === 'number' && isNaN(arg)) {
    return 'NaN';
  } else {
    return Object.prototype.toString.call(arg).slice(8, -1).toLowerCase();
  }
};

/**
 * 判断是否 json 数据
 * @param arg
 * @returns {string|null}
 */
const isJSON = arg => {
  if (typeof arg !== 'string') return null;
  try {
    const obj = JSON.parse(arg);
    return getType(obj);
  } catch (e) {
    return null;
  }
};

const Interceptors = {
  /**
   * 请求拦截器
   * @param {FlyRequestConfig} request
   * @returns {*}
   */
  async onSend(request) {
    //给所有请求添加自定义header
    process.env.NODE_ENV === 'development' && console.warn(request, '请求配置');
    //给所有请求添加自定义header
    request.headers['X-Tag'] = 'flyio';

    const token = uni.getStorageSync('token');
    if (token) {
      //给所有请求添加自定义header
      request.headers['Authorization'] = token;
    } else {
      this.lock();
      const { code, errMsg, resultCode } = await loginAsync();
      if (resultCode === 0) {
      }
      return;
    }

    const _t = Date.now() / 1000;

    // 防止缓存
    if (request.method === 'POST' && request.headers['Content-Type'] !== 'multipart/form-data') {
      request.body = Object.assign({}, request.body, { _t });
    } else if (request.method === 'GET') {
      request.params = Object.assign({}, request.params, { _t });
    }

    return request;
  },
  /**
   * 响应成功拦截器
   * @param {FlyResponse} response
   */
  async onSucceed(response) {
    let result = response?.data;
    const code = ['number', 'string'].includes(typeof result?.code) ? result?.code : -1;
    let message = result?.message;
    const self = this;

    if (typeof result === 'string') {
      try {
        result = JSON.parse(result);
      } catch (e) {}
    }

    const result2 = await nuni.getSystemInfoAsync();
    debugger;
    if (!result || getType(result) !== 'object') {
      message = '服务器响应格式错误';
      uni.showToast({
        title: `${message}(${code})`,
        icon: 'none'
      });
      return Promise.resolve({ code });
    }

    switch (true) {
      case code === 401:
        const newFly = createRequest();
        self.lock(); //锁住请求队列，先执行获取token操作
        const code = await nuni.getSystemInfoSync();
        return newFly
          .get(GET_MINI_PROGRAM_TOKEN_API, { code: code })
          .then(d => {
            //request.headers["token"]  = d.data.token;
            uni.setStorageSync('token', d.data.token);
          })
          .finally(() => self.unlock()) //解锁后，会继续发起请求队列中的任务
          .then(() => {
            console.log(`重新请求：path:${response.request.url}，baseURL:${response.request.baseURL}`);
            return fly.request(response.request);
          });
    }
    return;
  },
  /**
   * 响应失败拦截器
   * @param {Error} error
   */
  onError(error) {
    //发生网络错误后会走到这里
    return Promise.resolve('网络请求：ERROR！');
  }
};

/**
 * 创建请求
 * @param {number} timeout
 * @param {string} baseURL
 * @param {Object|*} headers
 * @returns {Fly}
 */
export function createRequest({ timeout = 15000, baseURL = BASE_URL, headers } = {}) {
  /**
   * @type {Fly}
   */
  const fly = new Fly();

  // #ifdef H5
  fly.engine = XMLHttpRequest;
  // #endif

  // 配置请求参数
  // /**
  //  *
  //  * @type {FlyRequestConfig}
  //  */
  const config = {};

  //实例级配置
  config.timeout = timeout;
  config.baseURL = baseURL;
  headers && (config.headers = headers);

  Object.assign(fly.config, config);
  fly.interceptors.request.use(Interceptors.onSend);
  fly.interceptors.response.use(Interceptors.onSucceed, Interceptors.onError);
  return fly;
}

export const fly = createRequest();
